#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
文件名称: constants.py
完整存储路径: backend/constants.py
功能说明:
    系统常量配置文件，包含字段映射、验证规则、选项配置等。
    本文件是系统的核心配置中心，各模块通过导入相应的映射表来实现数据处理。
"""

import re
from datetime import datetime

# ==================== 核心选项配置 ====================

# ✅ 修正视力等级配置 - 依据技术文档E标准（唯一定义）
VISION_LEVEL_OPTIONS = [
    "假性近视",      # 散瞳后SE=0，最高优先级
    "高度近视",      # SE < -6.00D
    "中度近视",      # -6.00D ≤ SE < -3.00D
    "轻度近视",      # -3.00D ≤ SE < -0.5D
    "正常视力",      # -0.5D ≤ SE ≤ +0.5D
    "临床前期近视",   # 年龄分层判定
    "远视"          # SE > +0.5D且≥13岁
]

# 基础选项配置
SCHOOL_OPTIONS = ["华兴小学", "苏宁红军小学", "师大附小清华小学"]
GRADE_OPTIONS = ["一年级", "二年级", "三年级", "四年级", "五年级", "六年级", "七年级", "八年级", "九年级"]
CLASS_OPTIONS = [f"{i}班" for i in range(1, 16)]
GENDER_OPTIONS = ["男", "女"]
DATA_YEAR_OPTIONS = ["2023", "2024", "2025", "2026", "2027", "2028"]
INTERVENTION_EFFECT_OPTIONS = ["上升", "维持", "下降"]
MYOPIA_DEGREE_OPTIONS = ["轻度近视", "中度近视", "高度近视"]

# 干预相关配置
INTERVENTION_SUBFIELDS = ["guasha", "aigiu", "zhongyao_xunzheng", "rejiu_training", "reci_pulse", "baoguan"]
INTERVENTION_OPTIONS = ["刮痧", "艾灸", "中药熏蒸", "热灸训练", "热磁脉冲", "拔罐"]

# 穴位选项配置（补充缺失配置）
ACUPOINT_OPTIONS = [
    "太阳穴", "印堂穴", "攒竹穴", "鱼腰穴", "丝竹空穴", "瞳子髎穴",
    "四白穴", "承泣穴", "睛明穴", "光明穴", "风池穴", "合谷穴",
    "足三里", "三阴交", "肝俞穴", "肾俞穴", "脾俞穴", "胃俞穴"
]

# 按压方法选项配置（补充缺失配置）
PRESS_METHOD_OPTIONS = [
    "轻度", "中度", "重度", "持续按压", "间歇按压", "旋转按压"
]

# ==================== 核心字段映射 ====================

FIELD_DISPLAY_MAPPING = {
    # 学生基本信息
    'education_id': '教育ID号', 'school': '学校', 'grade': '年级', 'class_name': '班级',
    'name': '姓名', 'gender': '性别', 'age': '年龄', 'birthday': '出生日期',
    'phone': '联系电话', 'parent_name': '家长姓名', 'parent_phone': '家长电话',
    'height': '身高', 'weight': '体重',
    
    # 健康信息
    'diet_preference': '饮食偏好', 'exercise_preference': '运动偏好', 'health_education': '健康教育',
    'past_history': '既往史', 'family_history': '家族史', 'premature': '是否早产', 'allergy': '过敏史',
    'correction_method': '矫正方式',
    
    # 视力相关字段
    'right_eye_naked': '右眼裸眼视力', 'left_eye_naked': '左眼裸眼视力',
    'right_eye_corrected': '右眼矫正视力', 'left_eye_corrected': '左眼矫正视力',
    'right_sphere': '右眼球镜', 'left_sphere': '左眼球镜',
    'right_cylinder': '右眼柱镜', 'left_cylinder': '左眼柱镜',
    'right_axis': '右眼轴位', 'left_axis': '左眼轴位',
    'left_se': '左眼SE值', 'right_se': '右眼SE值',
    'left_dilated_se': '左眼散瞳SE值', 'right_dilated_se': '右眼散瞳SE值',
    'myopia_degree': '近视程度', 'comprehensive_vision_level': '综合视力等级',
    
    # 散瞳验光字段
    'left_dilated_sphere': '左眼散瞳球镜', 'right_dilated_sphere': '右眼散瞳球镜',
    'left_dilated_cylinder': '左眼散瞳柱镜', 'right_dilated_cylinder': '右眼散瞳柱镜',
    'left_dilated_axis': '左眼散瞳轴位', 'right_dilated_axis': '右眼散瞳轴位',
    'left_dilated_vision': '左眼散瞳视力', 'right_dilated_vision': '右眼散瞳视力',
    
    # 基线对比字段
    'baseline_left_naked_change': '左眼裸眼视力变化值', 'baseline_right_naked_change': '右眼裸眼视力变化值',
    'baseline_left_sphere_change': '左眼球镜变化值', 'baseline_right_sphere_change': '右眼球镜变化值',
    'baseline_left_se_change': '左眼SE变化值', 'baseline_right_se_change': '右眼SE变化值',
    'baseline_left_cylinder_change': '左眼柱镜变化值', 'baseline_right_cylinder_change': '右眼柱镜变化值',
    'baseline_left_axis_change': '左眼轴位变化值', 'baseline_right_axis_change': '右眼轴位变化值',
    
    # 基线对比效果字段
    'baseline_right_vision_effect': '右眼干预效果', 'baseline_left_vision_effect': '左眼干预效果',
    'baseline_right_sphere_effect': '右眼球镜干预效果', 'baseline_left_sphere_effect': '左眼球镜干预效果',
    'baseline_right_cylinder_effect': '右眼柱镜干预效果', 'baseline_left_cylinder_effect': '左眼柱镜干预效果',
    'baseline_right_axis_effect': '右眼轴位干预效果', 'baseline_left_axis_effect': '左眼轴位干预效果',
    
    # 生物测量字段
    'left_keratometry_K1': '左眼角膜曲率K1', 'right_keratometry_K1': '右眼角膜曲率K1',
    'left_keratometry_K2': '左眼角膜曲率K2', 'right_keratometry_K2': '右眼角膜曲率K2',
    'left_axial_length': '左眼眼轴长度', 'right_axial_length': '右眼眼轴长度',
    'left_anterior_depth': '左眼前房深度', 'right_anterior_depth': '右眼前房深度',
    'other_info': '其他情况', 'eye_fatigue': '眼疲劳状况',
    
    # 测量相关字段
    'measurement_sequence': '测量序号', 'age_at_measure': '测量时年龄',
    'is_baseline': '是否基线', 'measure_date': '测量日期',
    'measure_type': '测量类型', 'measurer': '测量员',
    
    # 干预方式字段
    'guasha': '刮痧', 'aigiu': '艾灸', 'zhongyao_xunzheng': '中药熏蒸',
    'rejiu_training': '热灸训练', 'reci_pulse': '热磁脉冲', 'baoguan': '拔罐'
}

# ✅ 兼容性别名
# 🔧 修复：删除FIELD_LABEL_MAPPING别名，统一使用FIELD_DISPLAY_MAPPING
# FIELD_LABEL_MAPPING = FIELD_DISPLAY_MAPPING  # 已删除，统一使用FIELD_DISPLAY_MAPPING

# 完整字段列表（用于查询和统计分析）
COMPLETE_FIELDS = [
    # 基础字段
    "data_year", "education_id", "school", "grade", "class_name", "name", "gender", "age",
    
    # 视力等级字段
    "vision_level", "comprehensive_vision_level", "myopia_degree",
    
    # 基础视力字段
    "left_eye_naked", "right_eye_naked", "left_eye_corrected", "right_eye_corrected",
    
    # 屈光度字段
    "left_sphere", "right_sphere", "left_cylinder", "right_cylinder", "left_axis", "right_axis",
    "left_se", "right_se", "left_dilated_se", "right_dilated_se",
    
    # 散瞳验光字段
    "left_dilated_sphere", "right_dilated_sphere", "left_dilated_cylinder", "right_dilated_cylinder",
    "left_dilated_axis", "right_dilated_axis", "left_dilated_vision", "right_dilated_vision",
    
    # 基线对比字段
    "baseline_left_naked_change", "baseline_right_naked_change",
    "baseline_left_sphere_change", "baseline_right_sphere_change", 
    "baseline_left_cylinder_change", "baseline_right_cylinder_change",
    "baseline_left_axis_change", "baseline_right_axis_change",
    "baseline_left_se_change", "baseline_right_se_change",
    
    # 效果评估字段
    "baseline_left_vision_effect", "baseline_right_vision_effect",
    "baseline_left_sphere_effect", "baseline_right_sphere_effect", 
    "baseline_left_cylinder_effect", "baseline_right_cylinder_effect",
    "baseline_left_axis_effect", "baseline_right_axis_effect",
    "baseline_left_se_effect", "baseline_right_se_effect",
    
    # 生物测量字段
    "left_keratometry_K1", "right_keratometry_K1", "left_keratometry_K2", "right_keratometry_K2",
    "left_axial_length", "right_axial_length", "left_anterior_depth", "right_anterior_depth",
    
    # 干预方式字段
    "guasha", "aigiu", "zhongyao_xunzheng", "rejiu_training", "reci_pulse", "baoguan",
    "frame_glasses", "contact_lenses", "night_orthokeratology",
    
    # 测量相关字段
    "measurement_sequence", "age_at_measure", "is_baseline", "measure_date", "measure_type", "measurer",
    "other_info", "eye_fatigue"
]

# 查询字段配置元数据（唯一定义）
METRIC_CONFIG = {
    "education_id": {"label": "教育ID号", "type": "text", "valid_values": []},
    "school": {"label": "学校", "type": "multi-select", "options": SCHOOL_OPTIONS, "valid_values": SCHOOL_OPTIONS},
    "class_name": {"label": "班级", "type": "dropdown", "options": CLASS_OPTIONS, "valid_values": CLASS_OPTIONS},
    "name": {"label": "姓名", "type": "text", "valid_values": []},
    "gender": {"label": "性别", "type": "multi-select", "options": GENDER_OPTIONS, "valid_values": GENDER_OPTIONS},
    "age": {"label": "年龄", "type": "number_range", "input_type": "integer", "valid_values": []},
    "data_year": {"label": "数据年份", "type": "dropdown", "options": DATA_YEAR_OPTIONS, "valid_values": DATA_YEAR_OPTIONS},
    "grade": {"label": "年级", "type": "multi-select", "options": GRADE_OPTIONS, "valid_values": GRADE_OPTIONS},
    "vision_level": {"label": "视力等级", "type": "multi-select", "options": VISION_LEVEL_OPTIONS, "valid_values": VISION_LEVEL_OPTIONS},
    "interv_vision_level": {"label": "干预后视力等级", "type": "multi-select", "options": VISION_LEVEL_OPTIONS, "valid_values": VISION_LEVEL_OPTIONS},
    "comprehensive_vision_level": {"label": "综合视力等级", "type": "multi-select", "options": VISION_LEVEL_OPTIONS, "valid_values": VISION_LEVEL_OPTIONS},
    
    # 数值范围字段
    "left_eye_naked": {"label": "左眼-裸眼视力", "type": "number_range", "precision": 2, "valid_values": []},
    "right_eye_naked": {"label": "右眼-裸眼视力", "type": "number_range", "precision": 2, "valid_values": []},
    "left_eye_corrected": {"label": "左眼-矫正视力", "type": "number_range", "valid_values": []},
    "right_eye_corrected": {"label": "右眼-矫正视力", "type": "number_range", "valid_values": []},
    "left_sphere": {"label": "左眼球镜", "type": "number_range", "precision": 2, "valid_values": []},
    "right_sphere": {"label": "右眼球镜", "type": "number_range", "precision": 2, "valid_values": []},
    "left_cylinder": {"label": "左眼柱镜", "type": "number_range", "precision": 2, "valid_values": []},
    "right_cylinder": {"label": "右眼柱镜", "type": "number_range", "precision": 2, "valid_values": []},
    "left_axis": {"label": "左眼轴位", "type": "number_range", "precision": 1, "valid_values": []},
    "right_axis": {"label": "右眼轴位", "type": "number_range", "precision": 1, "valid_values": []},
    "left_se": {"label": "左眼SE值", "type": "number_range", "precision": 2, "valid_values": []},
    "right_se": {"label": "右眼SE值", "type": "number_range", "precision": 2, "valid_values": []},
    
    # 散瞳验光字段
    "left_dilated_sphere": {"label": "左眼散瞳球镜", "type": "number_range", "precision": 2, "valid_values": []},
    "right_dilated_sphere": {"label": "右眼散瞳球镜", "type": "number_range", "precision": 2, "valid_values": []},
    "left_dilated_se": {"label": "左眼散瞳SE值", "type": "number_range", "precision": 2, "valid_values": []},
    "right_dilated_se": {"label": "右眼散瞳SE值", "type": "number_range", "precision": 2, "valid_values": []},
    
    # 生物测量字段
    "left_keratometry_K1": {"label": "左眼-角膜曲率K1", "type": "number_range", "valid_values": []},
    "right_keratometry_K1": {"label": "右眼-角膜曲率K1", "type": "number_range", "valid_values": []},
    "left_axial_length": {"label": "左眼-眼轴", "type": "number_range", "valid_values": []},
    "right_axial_length": {"label": "右眼-眼轴", "type": "number_range", "valid_values": []},
    
    # 基线对比字段
    "baseline_left_naked_change": {"label": "左眼裸眼视力变化", "type": "number_range", "precision": 2, "valid_values": []},
    "baseline_right_naked_change": {"label": "右眼裸眼视力变化", "type": "number_range", "precision": 2, "valid_values": []},
    "baseline_left_sphere_change": {"label": "左眼球镜变化", "type": "number_range", "precision": 2, "valid_values": []},
    "baseline_right_sphere_change": {"label": "右眼球镜变化", "type": "number_range", "precision": 2, "valid_values": []},
    "baseline_left_se_change": {"label": "左眼SE变化", "type": "number_range", "precision": 2, "valid_values": []},
    "baseline_right_se_change": {"label": "右眼SE变化", "type": "number_range", "precision": 2, "valid_values": []},
    
    # 基线对比效果评估字段（新增）
    "baseline_left_vision_effect": {"label": "左眼视力干预效果", "type": "multi-select", "options": INTERVENTION_EFFECT_OPTIONS, "valid_values": INTERVENTION_EFFECT_OPTIONS},
    "baseline_right_vision_effect": {"label": "右眼视力干预效果", "type": "multi-select", "options": INTERVENTION_EFFECT_OPTIONS, "valid_values": INTERVENTION_EFFECT_OPTIONS},
    "baseline_left_se_effect": {"label": "左眼SE干预效果", "type": "multi-select", "options": INTERVENTION_EFFECT_OPTIONS, "valid_values": INTERVENTION_EFFECT_OPTIONS},
    "baseline_right_se_effect": {"label": "右眼SE干预效果", "type": "multi-select", "options": INTERVENTION_EFFECT_OPTIONS, "valid_values": INTERVENTION_EFFECT_OPTIONS},
    "baseline_left_sphere_effect": {"label": "左眼球镜干预效果", "type": "multi-select", "options": INTERVENTION_EFFECT_OPTIONS, "valid_values": INTERVENTION_EFFECT_OPTIONS},
    "baseline_right_sphere_effect": {"label": "右眼球镜干预效果", "type": "multi-select", "options": INTERVENTION_EFFECT_OPTIONS, "valid_values": INTERVENTION_EFFECT_OPTIONS},
    "baseline_left_cylinder_effect": {"label": "左眼柱镜干预效果", "type": "multi-select", "options": INTERVENTION_EFFECT_OPTIONS, "valid_values": INTERVENTION_EFFECT_OPTIONS},
    "baseline_right_cylinder_effect": {"label": "右眼柱镜干预效果", "type": "multi-select", "options": INTERVENTION_EFFECT_OPTIONS, "valid_values": INTERVENTION_EFFECT_OPTIONS},
    "baseline_left_axis_effect": {"label": "左眼轴位干预效果", "type": "multi-select", "options": INTERVENTION_EFFECT_OPTIONS, "valid_values": INTERVENTION_EFFECT_OPTIONS},
    "baseline_right_axis_effect": {"label": "右眼轴位干预效果", "type": "multi-select", "options": INTERVENTION_EFFECT_OPTIONS, "valid_values": INTERVENTION_EFFECT_OPTIONS},
    
    # 效果评估字段
    "left_interv_effect": {"label": "左眼视力干预效果", "type": "multi-select", "options": INTERVENTION_EFFECT_OPTIONS, "valid_values": INTERVENTION_EFFECT_OPTIONS},
    "right_interv_effect": {"label": "右眼视力干预效果", "type": "multi-select", "options": INTERVENTION_EFFECT_OPTIONS, "valid_values": INTERVENTION_EFFECT_OPTIONS},
    
    # 近视程度配置
    "myopia_degree": {"label": "近视程度", "type": "multi-select", "options": MYOPIA_DEGREE_OPTIONS, "valid_values": MYOPIA_DEGREE_OPTIONS},
    
    # 测量相关字段
    "measurement_sequence": {"label": "测量序号", "type": "number_range", "input_type": "integer", "valid_values": []},
    "age_at_measure": {"label": "测量时年龄", "type": "number_range", "input_type": "integer", "valid_values": []},
    "is_baseline": {"label": "是否基线", "type": "multi-select", "options": ["是", "否"], "valid_values": [True, False]}
}

# Excel字段映射（唯一定义）
EXCEL_FIELD_MAPPING = {
    # 基本信息字段 - 完全匹配Excel列头
    '教育ID号': 'education_id', 
    '学校': 'school', 
    '年级': 'grade', 
    '班级': 'class_name',
    '姓名': 'name', 
    '性别': 'gender', 
    '年龄': 'age', 
    '身高': 'height', 
    '体重': 'weight',
    '出生日期': 'birthday',  # ✅ 修正：保持正确的"出生日期"
    '身份证号码': 'id_card', 
    '联系电话': 'phone', 
    '家长姓名': 'parent_name', 
    '家长电话': 'parent_phone',
    '联系地址': 'contact_address', 
    '区域': 'region',
    
    # 健康信息字段 - 完全匹配Excel列头
    '饮食偏好': 'diet_preference', 
    '运动偏好': 'exercise_preference', 
    '健康教育': 'health_education',
    '既往史': 'past_history', 
    '家族史': 'family_history', 
    '是否早产': 'premature', 
    '过敏史': 'allergy',
    
    # 矫正方式字段 - 完全匹配Excel列头
    '框架眼镜': 'frame_glasses', 
    '隐形眼镜': 'contact_lenses', 
    '夜戴角膜塑型镜': 'night_orthokeratology',
    
    # 干预方式字段 - 完全匹配Excel列头
    '刮痧': 'guasha', 
    '艾灸': 'aigiu', 
    '中药熏蒸': 'zhongyao_xunzheng',
    '热灸训练': 'rejiu_training', 
    '耳穴压丸': 'erxue_yawan',  # ✅ 修正：保持正确的"耳穴压丸"
    '热磁脉冲': 'reci_pulse', 
    '拔罐': 'baoguan',
    
    # 基线视力数据字段 - 完全匹配Excel列头
    '右眼-裸眼视力': 'right_eye_naked', 
    '左眼-裸眼视力': 'left_eye_naked',
    '右眼-矫正视力': 'right_eye_corrected', 
    '左眼-矫正视力': 'left_eye_corrected',
    '右眼-角膜曲率K1': 'right_keratometry_K1', 
    '左眼-角膜曲率K1': 'left_keratometry_K1',
    '右眼-角膜曲率K2': 'right_keratometry_K2', 
    '左眼-角膜曲率K2': 'left_keratometry_K2',
    '右眼-眼轴': 'right_axial_length', 
    '左眼-眼轴': 'left_axial_length',
    
    # 基线屈光数据字段 - 完全匹配Excel列头
    '右眼屈光-球镜': 'right_sphere', 
    '右眼屈光-柱镜': 'right_cylinder', 
    '右眼屈光-轴位': 'right_axis',
    '左眼屈光-球镜': 'left_sphere', 
    '左眼屈光-柱镜': 'left_cylinder', 
    '左眼屈光-轴位': 'left_axis',  # ✅ 修正：保持正确的"左眼屈光-轴位"
    
    # 散瞳验光数据字段 - 完全匹配Excel列头
    '右眼散瞳-球镜': 'right_dilated_sphere', 
    '左眼散瞳-球镜': 'left_dilated_sphere',
    '右眼散瞳-柱镜': 'right_dilated_cylinder', 
    '左眼散瞳-柱镜': 'left_dilated_cylinder',
    '右眼散瞳-轴位': 'right_dilated_axis', 
    '左眼散瞳-轴位': 'left_dilated_axis',
    
    # 其他检查数据字段 - 完全匹配Excel列头
    '右眼-前房深度': 'right_anterior_depth', 
    '左眼-前房深度': 'left_anterior_depth',
    '其他情况': 'other_info', 
    '眼疲劳状况': 'eye_fatigue',
    
    # 随访（干预后）视力数据字段 - 完全匹配Excel列头
    '右眼-干预-裸眼视力': 'right_eye_naked',  # ✅ 映射到相同字段
    '左眼-干预-裸眼视力': 'left_eye_naked',   # ✅ 映射到相同字段
    
    # 随访（干预后）屈光数据字段 - 完全匹配Excel列头
    '右眼屈光-干预-球镜': 'right_sphere',     # ✅ 映射到相同字段
    '右眼屈光-干预-柱镜': 'right_cylinder',   # ✅ 映射到相同字段
    '右眼屈光-干预-轴位': 'right_axis',       # ✅ 映射到相同字段
    '左眼屈光-干预-球镜': 'left_sphere',      # ✅ 映射到相同字段
    '左眼屈光-干预-柱镜': 'left_cylinder',    # ✅ 映射到相同字段
    '左眼屈光-干预-轴位': 'left_axis',        # ✅ 映射到相同字段
    
    # 随访（干预后）散瞳数据字段 - 完全匹配Excel列头
    '右眼散瞳-干预-球镜': 'right_dilated_sphere',    # ✅ 映射到相同字段
    '右眼散瞳-干预-柱镜': 'right_dilated_cylinder',  # ✅ 映射到相同字段
    '右眼散瞳-干预-轴位': 'right_dilated_axis',      # ✅ 映射到相同字段
    '左眼散瞳-干预-球镜': 'left_dilated_sphere',     # ✅ 映射到相同字段
    '左眼散瞳-干预-柱镜': 'left_dilated_cylinder',   # ✅ 映射到相同字段
    '左眼散瞳-干预-轴位': 'left_dilated_axis',       # ✅ 映射到相同字段
    
    # 干预日期字段 - 支持最多12次干预
    '第1次干预': 'intervention_date_1',   '第2次干预': 'intervention_date_2',
    '第3次干预': 'intervention_date_3',   '第4次干预': 'intervention_date_4',
    '第5次干预': 'intervention_date_5',   '第6次干预': 'intervention_date_6',
    '第7次干预': 'intervention_date_7',   '第8次干预': 'intervention_date_8',
    '第9次干预': 'intervention_date_9',   '第10次干预': 'intervention_date_10',
    '第11次干预': 'intervention_date_11', '第12次干预': 'intervention_date_12'
}

# ✅ 添加measure_location字段配置
FIELD_DISPLAY_MAPPING.update({
    'measure_location': '检测地点（机构）'
})

EXCEL_FIELD_MAPPING.update({
    '检测地点（机构）': 'measure_location'
})

# 更新字段显示映射（补充缺失字段）
FIELD_DISPLAY_MAPPING.update({
    # StudentExtension模型字段补充
    'correction_method': '矫正方式',
    'frame_glasses': '框架眼镜',
    'contact_lenses': '隐形眼镜', 
    'night_orthokeratology': '夜戴角膜塑型镜',
    
    # VisionRecord模型字段确认
    'measure_location': '检查地点（机构）',  # 已存在，确认无误
    
    # 完善其他可能缺失的字段
    'left_dilated_vision': '左眼散瞳视力',
    'right_dilated_vision': '右眼散瞳视力',
})

# 更新Excel字段映射（补充缺失映射）
EXCEL_FIELD_MAPPING.update({
    # 矫正方式相关
    '矫正方式': 'correction_method',
    '框架眼镜': 'frame_glasses',
    '隐形眼镜': 'contact_lenses',
    '夜戴角膜塑型镜': 'night_orthokeratology',
    
    # 检查地点确认
    '检查地点（机构）': 'measure_location',  # 已存在，确认无误
    
    # 散瞳视力字段
    '左眼散瞳视力': 'left_dilated_vision',
    '右眼散瞳视力': 'right_dilated_vision',
})

# ==================== 数据验证配置 ====================

DATE_FORMATS = ['%Y-%m-%d', '%Y/%m/%d', '%Y.%m.%d', '%Y-%m-%d %H:%M:%S', '%Y/%m/%d %H:%M:%S', '%m/%d/%Y', '%d/%m/%Y', '%Y%m%d']

VALIDATION_RULES = {
    'education_id': r'^\d{7,20}$',
    'gender': ['男', '女'],
    'phone': r'^1[3-9]\d{9}$',
    'id_card': r'^\d{17}[\dXx]$'
}

MEDICAL_VALUE_RANGES = {
    'vision': (0.1, 5.3), 'age': (3, 18), 'height': (80, 200), 'weight': (10, 100),
    'sphere': (-20.0, 20.0), 'cylinder': (-10.0, 10.0), 'axis': (0, 180),
    'keratometry': (35.0, 50.0), 'axial_length': (18.0, 30.0), 'anterior_depth': (2.0, 5.0),
}

NUMERIC_VALIDATION_RANGES = {
    'age': {'min': 3, 'max': 18, 'type': 'integer', 'name': '年龄'},
    'height': {'min': 80, 'max': 200, 'type': 'float', 'name': '身高(cm)'},
    'weight': {'min': 10, 'max': 100, 'type': 'float', 'name': '体重(kg)'},
    'vision': {'min': 0.1, 'max': 5.3, 'type': 'float', 'name': '视力'},
    'sphere': {'min': -20.0, 'max': 20.0, 'type': 'float', 'name': '球镜(D)'},
    'cylinder': {'min': -10.0, 'max': 10.0, 'type': 'float', 'name': '柱镜(D)'},
    'axis': {'min': 0, 'max': 180, 'type': 'float', 'name': '轴位(度)'},
    'keratometry': {'min': 35.0, 'max': 50.0, 'type': 'float', 'name': '角膜曲率(D)'},
    'axial_length': {'min': 18.0, 'max': 30.0, 'type': 'float', 'name': '眼轴长度(mm)'},
    'anterior_depth': {'min': 2.0, 'max': 5.0, 'type': 'float', 'name': '前房深度(mm)'},
}

DATA_VALIDATION_PATTERNS = {
    'id_card': r'^\d{17}[\dXx]$',
    'phone': r'^1[3-9]\d{9}$',
    'education_id': r'^\d{7,20}$',
    'parent_phone': r'^1[3-9]\d{9}$'
}

# ==================== 年级升级配置 ====================

GRADE_UPGRADE_MAPPING = {
    "一年级": "二年级", "二年级": "三年级", "三年级": "四年级",
    "四年级": "五年级", "五年级": "六年级", "六年级": "七年级",
    "七年级": "八年级", "八年级": "九年级", "九年级": "高一",
    "高一": "高二", "高二": "高三", "高三": "高三"
}

def upgrade_grade(current_grade):
    """升级年级"""
    return GRADE_UPGRADE_MAPPING.get(current_grade, current_grade)

# ==================== 干预配置 ====================

INTERVENTION_IMPORT_DEFAULTS = {
    'intervention_type': '穴位贴敷', 'operator': '系统导入', 'details': 'Excel批量导入数据',
    'press_strength': '中度', 'is_imported': True, 'operation_time': '09:00',
    'session_number': 1, 'duration_minutes': 30, 'import_source': 'Excel导入'
}

EXTENSION_FIELD_INHERITANCE = {
    "relatively_fixed": ['past_history', 'family_history', 'premature', 'allergy'],
    "health_variable": ['diet_preference', 'exercise_preference', 'health_education', 'correction_method', 'frame_glasses', 'contact_lenses', 'night_orthokeratology']
}

# ==================== 图表配色 ====================

CHART_COLORS = {
    'METRICS': {
        '上升': '#2ecc71', '维持': '#f1c40f', '下降': '#e74c3c',
        '临床前期近视': '#3498db', '轻度近视': '#9b59b6', '中度近视': '#e67e22',
        '假性近视': '#1abc9c', '正常': '#2ecc71'
    },
    'EXTENDED': ['#1abc9c', '#2ecc71', '#3498db', '#9b59b6', '#f1c40f', '#e67e22', '#e74c3c', '#34495e']
}

# ==================== 固定指标和字段分组 ====================

# ✅ 修正：FIXED_METRICS应该是列表
FIXED_METRICS = ['education_id', 'name', 'school', 'grade', 'class_name', 'gender', 'age', 'left_eye_naked', 'right_eye_naked', 'vision_level']

# 字段分组（保留不同模块可能引用）
BASELINE_VISION_EXCEL_FIELDS = [
    '右眼-裸眼视力', '左眼-裸眼视力', '右眼-矫正视力', '左眼-矫正视力',
    '右眼-角膜曲率K1', '左眼-角膜曲率K1', '右眼-角膜曲率K2', '左眼-角膜曲率K2',
    '右眼-眼轴', '左眼-眼轴',
    '右眼屈光-球镜', '右眼屈光-柱镜', '右眼屈光-轴位',
    '左眼屈光-球镜', '左眼屈光-柱镜', '左眼-屈光轴位',
    '右眼散瞳-球镜', '右眼散瞳-柱镜', '右眼散瞳-轴位',
    '左眼散瞳-球镜', '左眼散瞳-柱镜', '左眼散瞳-轴位',
    '右眼-前房深度', '左眼-前房深度', '其他情况', '眼疲劳状况'
]

FOLLOWUP_VISION_EXCEL_FIELDS = [
    '右眼-干预-裸眼视力', '左眼-干预-裸眼视力',
    '右眼屈光-干预-球镜', '右眼屈光-干预-柱镜', '右眼屈光-干预-轴位',
    '左眼屈光-干预-球镜', '左眼屈光-干预-柱镜', '左眼屈光-干预-轴位',
    '右眼散瞳-干预-球镜', '右眼散瞳-干预-柱镜', '右眼散瞳-干预-轴位',
    '左眼散瞳-干预-球镜', '左眼散瞳-干预-柱镜', '左眼散瞳-干预-轴位'
]

VISION_RECORD_FIELDS = [
    # 基础视力字段
    'right_eye_naked', 'left_eye_naked', 'right_eye_corrected', 'left_eye_corrected',
    # 生物测量字段
    'right_keratometry_K1', 'left_keratometry_K1', 'right_keratometry_K2', 'left_keratometry_K2',
    'right_axial_length', 'left_axial_length', 'right_anterior_depth', 'left_anterior_depth',
    # 屈光度字段
    'right_sphere', 'right_cylinder', 'right_axis', 'left_sphere', 'left_cylinder', 'left_axis',
    # 散瞳验光字段
    'right_dilated_sphere', 'right_dilated_cylinder', 'right_dilated_axis',
    'left_dilated_sphere', 'left_dilated_cylinder', 'left_dilated_axis',
    'left_dilated_vision', 'right_dilated_vision',
    # 计算字段
    'left_se', 'right_se', 'left_dilated_se', 'right_dilated_se',
    'left_vision_level', 'right_vision_level', 'comprehensive_vision_level', 'vision_level', 'myopia_degree',
    # 基线对比字段
    'baseline_left_naked_change', 'baseline_right_naked_change',
    'baseline_left_sphere_change', 'baseline_right_sphere_change',
    'baseline_left_se_change', 'baseline_right_se_change',
    'baseline_left_cylinder_change', 'baseline_right_cylinder_change',
    'baseline_left_axis_change', 'baseline_right_axis_change',
    # 效果评估字段
    'baseline_left_vision_effect', 'baseline_right_vision_effect',
    'baseline_left_sphere_effect', 'baseline_right_sphere_effect',
    'baseline_left_se_effect', 'baseline_right_se_effect',
    'baseline_left_cylinder_effect', 'baseline_right_cylinder_effect',
    'baseline_left_axis_effect', 'baseline_right_axis_effect',
    # 其他字段
    'other_info', 'eye_fatigue',
    # 元数据字段
    'measurement_sequence', 'age_at_measure', 'is_baseline', 'measure_date', 'measure_type', 'measurer', 'data_year'
]

# ==================== 随访记录相关配置（基于实际数据模型） ====================

# 随访字段显示映射（与实际模型字段完全一致）
FOLLOWUP_FIELD_DISPLAY_MAPPING = {
    # 随访基本信息（实际模型字段）
    'followup_date': '随访日期',
    'followup_time': '随访时间',
    'interviewer': '随访员',
    'interviewee': '被访者姓名', 
    'interviewee_relation': '与学生关系',
    'contact_method': '联系方式',
    'followup_duration': '随访时长',
    'followup_type': '随访类型',
    
    # 干预评价信息（实际模型字段）
    'intervention_satisfaction': '治疗满意度',
    'intervention_effect_evaluation': '效果评价',
    'intervention_compliance': '治疗依从性', 
    'side_effects': '不良反应',
    
    # 视力变化情况（实际模型字段）
    'vision_change_perception': '视力变化感知',
    'vision_improvement_details': '改善具体表现',
    'vision_concern_areas': '关心的问题',
    
    # 用眼情况（实际模型字段）
    'daily_eye_use_time': '每日用眼时间',
    
    # 系统字段
    'created_at': '创建时间',
    'updated_at': '更新时间'
}

# 随访选项配置（基于实际业务需求）
FOLLOWUP_OPTIONS = {
    "interviewee_relations": ["父亲", "母亲", "爷爷", "奶奶", "外公", "外婆", "其他"],
    "contact_methods": ["电话", "微信", "当面", "其他"],
    "followup_types": ["定期随访", "主动随访", "问题随访", "复查随访"],
    "satisfaction_levels": ["很满意", "满意", "一般", "不满意", "很不满意"],
    "effect_evaluations": ["显著", "有效", "一般", "无效"],
    "compliance_levels": ["很好", "较好", "一般", "较差", "很差"],
    "vision_change_perceptions": ["明显好转", "有所好转", "无变化", "有所恶化", "明显恶化"]
}

# 随访Excel字段映射（基于实际模型字段）
FOLLOWUP_EXCEL_MAPPING = {
    '随访日期': 'followup_date',
    '随访时间': 'followup_time',
    '随访员': 'interviewer', 
    '被访者姓名': 'interviewee',
    '与学生关系': 'interviewee_relation',
    '联系方式': 'contact_method',
    '随访时长': 'followup_duration',
    '随访类型': 'followup_type',
    '治疗满意度': 'intervention_satisfaction',
    '效果评价': 'intervention_effect_evaluation',
    '治疗依从性': 'intervention_compliance',
    '不良反应': 'side_effects',
    '视力变化感知': 'vision_change_perception',
    '改善具体表现': 'vision_improvement_details',
    '关心的问题': 'vision_concern_areas',
    '每日用眼时间': 'daily_eye_use_time'
}

# 更新主字段映射字典
FIELD_DISPLAY_MAPPING.update(FOLLOWUP_FIELD_DISPLAY_MAPPING)
EXCEL_FIELD_MAPPING.update(FOLLOWUP_EXCEL_MAPPING)

# 随访记录字段列表（基于实际模型）
FOLLOWUP_RECORD_FIELDS = [
    'followup_date', 'followup_time', 'interviewer', 'interviewee',
    'interviewee_relation', 'contact_method', 'followup_duration', 'followup_type',
    'intervention_satisfaction', 'intervention_effect_evaluation', 
    'intervention_compliance', 'side_effects', 'vision_change_perception',
    'vision_improvement_details', 'vision_concern_areas', 'daily_eye_use_time',
    'created_at', 'updated_at'
]

# 随访数据验证规则（基于实际模型字段）
FOLLOWUP_VALIDATION_RULES = {
    'followup_date': {'required': True, 'type': 'date'},
    'interviewer': {'required': True, 'max_length': 50},
    'interviewee': {'required': True, 'max_length': 50},
    'interviewee_relation': {'required': True, 'options': FOLLOWUP_OPTIONS['interviewee_relations']},
    'contact_method': {'required': True, 'options': FOLLOWUP_OPTIONS['contact_methods']},
    'followup_type': {'required': True, 'options': FOLLOWUP_OPTIONS['followup_types']},
    'intervention_satisfaction': {'options': FOLLOWUP_OPTIONS['satisfaction_levels']},
    'intervention_effect_evaluation': {'options': FOLLOWUP_OPTIONS['effect_evaluations']},
    'intervention_compliance': {'options': FOLLOWUP_OPTIONS['compliance_levels']},
    'vision_change_perception': {'options': FOLLOWUP_OPTIONS['vision_change_perceptions']},
    'side_effects': {'max_length': 200},
    'vision_improvement_details': {'type': 'text'},
    'vision_concern_areas': {'type': 'text'},
    'daily_eye_use_time': {'max_length': 50}
}

# 随访字段分组（用于前端表单组织）
FOLLOWUP_FIELD_GROUPS = {
    "基本信息": {
        "fields": ["followup_date", "followup_time", "interviewer", "interviewee", "interviewee_relation", "contact_method"],
        "required": True,
        "order": 1
    },
    "干预评价": {
        "fields": ["intervention_satisfaction", "intervention_effect_evaluation", "intervention_compliance", "side_effects"],
        "required": False,
        "order": 2
    },
    "视力变化": {
        "fields": ["vision_change_perception", "vision_improvement_details", "vision_concern_areas"],
        "required": False,
        "order": 3
    },
    "用眼情况": {
        "fields": ["daily_eye_use_time"],
        "required": False,
        "order": 4
    }
}

# ==================== 标准化函数 ====================

def normalize_grade(grade_input):
    """标准化年级数据"""
    if not grade_input:
        return None
    grade_mapping = {
        '1': '一年级', '2': '二年级', '3': '三年级', '4': '四年级', '5': '五年级', '6': '六年级',
        '7': '七年级', '8': '八年级', '9': '九年级',
        '一': '一年级', '二': '二年级', '三': '三年级', '四': '四年级', '五': '五年级', '六': '六年级',
        '七': '七年级', '八': '八年级', '九': '九年级',
        '初一': '七年级', '初二': '八年级', '初三': '九年级',
        '高一': '高一', '高二': '高二', '高三': '高三',
    }
    return grade_mapping.get(str(grade_input).strip(), str(grade_input).strip())

def normalize_class(class_input):
    """标准化班级数据"""
    if not class_input:
        return None
    class_mapping = {
        **{str(i): f'{i}班' for i in range(1, 16)},
        **{['一', '二', '三', '四', '五', '六', '七', '八', '九', '十', '十一', '十二', '十三', '十四', '十五'][i-1]: f'{i}班' for i in range(1, 16)}
    }
    return class_mapping.get(str(class_input).strip(), str(class_input).strip())

def normalize_gender(gender_input):
    """标准化性别数据"""
    if not gender_input:
        return None
    gender_mapping = {'男': '男', '女': '女', '未知': '未知'}
    return gender_mapping.get(str(gender_input).strip(), str(gender_input).strip())

def normalize_vision(vision_input):
    """标准化视力值"""
    if vision_input is None:
        return None
    try:
        vision_value = float(vision_input)
        return round(max(0.1, min(5.3, vision_value)), 1)
    except ValueError:
        return None

def normalize_phone(phone_input):
    """标准化手机号"""
    if not phone_input:
        return None
    phone_digits = re.sub(r'\D', '', str(phone_input))
    return phone_digits if len(phone_digits) == 11 and phone_digits.startswith('1') else None

def normalize_id_card(id_card_input):
    """标准化身份证号"""
    if not id_card_input:
        return None
    id_card_str = str(id_card_input).strip()
    return id_card_str.upper() if re.match(r'^\d{17}[\dXx]$', id_card_str) else None

def calculate_age_for_year(student_id, target_year):
    """计算学生在指定年份的年龄"""
    try:
        from backend.models.student import Student
        student = Student.query.get(student_id)
        if not student or not student.birthday:
            return None
        age = int(target_year) - student.birthday.year
        return age if age >= 0 else None
    except Exception as e:
        print(f"计算年龄失败: {e}")
        return None

def estimate_grade_by_age(age):
    """根据年龄估算年级"""
    if not age or age < 6:
        return None
    age_grade_mapping = {
        6: '一年级', 7: '二年级', 8: '三年级', 9: '四年级', 10: '五年级', 11: '六年级',
        12: '七年级', 13: '八年级', 14: '九年级', 15: '高一', 16: '高二', 17: '高三', 18: '高三'
    }
    return age_grade_mapping.get(age, '未知年级')

# ==================== 其他配置（保留不同模块可能的引用） ====================

# 统计相关配置（用于analysis模块）
STATISTICAL_METRICS = {
    'vision_improvement_rate': {'name': '视力改善率', 'description': '裸眼视力提升≥0.1的学生比例', 'unit': '%', 'calculation': 'percentage'},
    'myopia_prevention_rate': {'name': '近视预防率', 'description': '临床前期近视未发展为轻度近视的比例', 'unit': '%', 'calculation': 'percentage'},
    'myopia_progression_control_rate': {'name': '近视进展控制率', 'description': 'SE变化≤-0.25D的学生比例', 'unit': '%', 'calculation': 'percentage'},
    'comprehensive_effectiveness_rate': {'name': '综合有效率', 'description': '视力改善或SE稳定的学生比例', 'unit': '%', 'calculation': 'percentage'}
}

# ==================== 查询模块专用配置（新增） ====================

# 查询系统字段分组配置
QUERY_FIELD_GROUPS = {
    "基本信息字段组": {
        "priority": 1,
        "default_expanded": True,
        "table": "students",
        "fields": {
            "id": {"type": "number", "display": "学生ID", "validation": "number", "table": "students"},  # 修正：添加缺失的ID字段
            "education_id": {"type": "text", "display": "教育ID号", "validation": "text", "table": "students"},
            "name": {"type": "text", "display": "姓名", "validation": "text", "table": "students"},
            "gender": {"type": "multi_select", "display": "性别", "options": GENDER_OPTIONS, "table": "students"},
            "age": {"type": "number_range", "display": "年龄", "min": 3, "max": 18, "table": "student_extensions"},
            "school": {"type": "multi_select", "display": "学校", "options": SCHOOL_OPTIONS, "table": "students"},
            "grade": {"type": "multi_select", "display": "年级", "options": GRADE_OPTIONS, "table": "student_extensions"},
            "class_name": {"type": "text", "display": "班级", "validation": "text", "table": "students"},
            "data_year": {"type": "dropdown", "display": "数据年份", "options": DATA_YEAR_OPTIONS, "table": "student_extensions"}
        }
    },
    "视力等级字段组": {
        "priority": 2,
        "default_expanded": True,
        "table": "vision_records",
        "fields": {
            "comprehensive_vision_level": {"type": "multi_select", "display": "综合视力等级", "options": VISION_LEVEL_OPTIONS, "table": "vision_records"},
            "vision_level": {"type": "multi_select", "display": "视力等级", "options": VISION_LEVEL_OPTIONS, "table": "vision_records"}
        }
    },
    "视力数据字段组": {
        "priority": 3,
        "default_expanded": True,
        "table": "vision_records",
        "fields": {
            "left_eye_naked": {"type": "number_range", "display": "左眼裸眼视力", "min": 3.0, "max": 5.3, "table": "vision_records"},
            "right_eye_naked": {"type": "number_range", "display": "右眼裸眼视力", "min": 3.0, "max": 5.3, "table": "vision_records"},
            "left_eye_corrected": {"type": "number_range", "display": "左眼矫正视力", "min": 3.0, "max": 5.3, "table": "vision_records"},
            "right_eye_corrected": {"type": "number_range", "display": "右眼矫正视力", "min": 3.0, "max": 5.3, "table": "vision_records"},
            "left_se": {"type": "number_range", "display": "左眼等效球镜", "min": -20.0, "max": 20.0, "table": "vision_records"},
            "right_se": {"type": "number_range", "display": "右眼等效球镜", "min": -20.0, "max": 20.0, "table": "vision_records"}
        }
    },
    "基线对比字段组": {
        "priority": 4,
        "default_expanded": False,
        "table": "vision_records",
        "fields": {
            "baseline_left_naked_change": {"type": "number_range", "display": "左眼裸眼视力变化", "min": -3.0, "max": 3.0, "table": "vision_records"},
            "baseline_right_naked_change": {"type": "number_range", "display": "右眼裸眼视力变化", "min": -3.0, "max": 3.0, "table": "vision_records"},
            "baseline_left_sphere_change": {"type": "number_range", "display": "左眼球镜变化", "min": -10.0, "max": 10.0, "table": "vision_records"},
            "baseline_right_sphere_change": {"type": "number_range", "display": "右眼球镜变化", "min": -10.0, "max": 10.0, "table": "vision_records"},
            "baseline_left_se_change": {"type": "number_range", "display": "左眼SE变化", "min": -10.0, "max": 10.0, "table": "vision_records"},
            "baseline_right_se_change": {"type": "number_range", "display": "右眼SE变化", "min": -10.0, "max": 10.0, "table": "vision_records"},
            "baseline_left_cylinder_change": {"type": "number_range", "display": "左眼柱镜变化", "min": -10.0, "max": 10.0, "table": "vision_records"},
            "baseline_right_cylinder_change": {"type": "number_range", "display": "右眼柱镜变化", "min": -10.0, "max": 10.0, "table": "vision_records"},
            "baseline_left_axis_change": {"type": "number_range", "display": "左眼轴位变化", "min": -10.0, "max": 10.0, "table": "vision_records"},
            "baseline_right_axis_change": {"type": "number_range", "display": "右眼轴位变化", "min": -10.0, "max": 10.0, "table": "vision_records"},
        }
    }
}

# 查询模块专用字段映射生成函数
def generate_query_field_mappings():
    """基于QUERY_FIELD_GROUPS生成查询模块专用的字段映射配置"""
    field_display_mapping = {}
    field_config_mapping = {}
    field_type_mapping = {}
    field_validation_mapping = {}
    field_options_mapping = {}
    table_mapping = {}
    
    for group_name, group_config in QUERY_FIELD_GROUPS.items():
        default_table_name = group_config.get('table', 'students')  # 分组默认表
        
        for field_name, field_config in group_config.get('fields', {}).items():
            # 显示名称映射
            field_display_mapping[field_name] = field_config.get('display', field_name)
            
            # 获取字段的实际表名（优先使用字段级别的table配置）
            actual_table = field_config.get('table', default_table_name)
            
            # 完整配置映射
            field_config_mapping[field_name] = {
                'display': field_config.get('display', field_name),
                'type': field_config.get('type', 'text'),
                'validation': field_config.get('validation', 'text'),
                'group': group_name,
                'table': actual_table,  # 修正：使用实际表名
                'priority': group_config.get('priority', 999),
                'min': field_config.get('min'),
                'max': field_config.get('max'),
                'options': field_config.get('options', [])
            }
            
            # 字段类型映射
            field_type_mapping[field_name] = field_config.get('type', 'text')
            
            # 验证规则映射
            field_validation_mapping[field_name] = field_config.get('validation', 'text')
            
            # 选项映射
            if 'options' in field_config:
                field_options_mapping[field_name] = field_config['options']
            
            # 表映射 - 修正：使用实际表名
            table_mapping[field_name] = actual_table
    
    return {
        'field_display_mapping': field_display_mapping,
        'field_config_mapping': field_config_mapping,
        'field_type_mapping': field_type_mapping,
        'field_validation_mapping': field_validation_mapping,
        'field_options_mapping': field_options_mapping,
        'table_mapping': table_mapping
    }

# 生成查询模块专用配置
QUERY_FIELD_MAPPINGS = generate_query_field_mappings()

# 查询模块专用配置访问接口
QUERY_FIELD_DISPLAY_MAPPING = QUERY_FIELD_MAPPINGS['field_display_mapping']
QUERY_FIELD_CONFIG_MAPPING = QUERY_FIELD_MAPPINGS['field_config_mapping'] 
QUERY_FIELD_TYPE_MAPPING = QUERY_FIELD_MAPPINGS['field_type_mapping']
QUERY_FIELD_VALIDATION_MAPPING = QUERY_FIELD_MAPPINGS['field_validation_mapping']
QUERY_FIELD_OPTIONS_MAPPING = QUERY_FIELD_MAPPINGS['field_options_mapping']
QUERY_TABLE_MAPPING = QUERY_FIELD_MAPPINGS['table_mapping']

# 查询模块专用显示列配置
QUERY_DEFAULT_DISPLAY_COLUMNS = {
    "always_visible": ["id", "education_id", "name", "gender", "age", "school", "grade", "class_name"],  # 修正：添加id字段
    "default_selected": ["comprehensive_vision_level", "left_eye_naked", "right_eye_naked", 
                        "baseline_left_naked_change", "baseline_right_naked_change"],
    "available_columns": list(QUERY_FIELD_DISPLAY_MAPPING.keys()),
    "column_groups": {},
    "field_display_mapping": QUERY_FIELD_DISPLAY_MAPPING
}

# 生成查询模块专用分组配置
for group_name, group_config in QUERY_FIELD_GROUPS.items():
    QUERY_DEFAULT_DISPLAY_COLUMNS["column_groups"][group_name] = {
        "display": group_name,
        "priority": group_config.get('priority', 999),
        "default_expanded": group_config.get('default_expanded', False),
        "fields": list(group_config['fields'].keys())
    }

# 查询模块专用配置访问函数
def get_query_field_display_name(field_name):
    """查询模块专用：获取字段显示名称"""
    return QUERY_FIELD_DISPLAY_MAPPING.get(field_name, field_name)

def get_query_field_config(field_name):
    """查询模块专用：获取字段完整配置"""
    return QUERY_FIELD_CONFIG_MAPPING.get(field_name, {})

def get_query_field_type(field_name):
    """查询模块专用：获取字段类型"""
    return QUERY_FIELD_TYPE_MAPPING.get(field_name, 'text')

def get_query_field_table(field_name):
    """查询模块专用：获取字段所属表"""
    return QUERY_TABLE_MAPPING.get(field_name, 'students')

def get_query_field_options(field_name):
    """查询模块专用：获取字段选项列表"""
    return QUERY_FIELD_OPTIONS_MAPPING.get(field_name, [])

def validate_query_fields(field_names):
    """查询模块专用：验证查询字段的有效性"""
    valid_fields = []
    invalid_fields = []
    
    for field_name in field_names:
        if field_name in QUERY_FIELD_CONFIG_MAPPING:
            valid_fields.append(field_name)
        else:
            invalid_fields.append(field_name)
    
    return {
        'valid_fields': valid_fields,
        'invalid_fields': invalid_fields,
        'is_valid': len(invalid_fields) == 0
    }

def format_vision_check_time(measure_date, measure_time):
    """格式化视力检查时间"""
    if not measure_date:
        return ""
    
    date_str = measure_date.strftime('%Y-%m-%d') if hasattr(measure_date, 'strftime') else str(measure_date)
    
    if measure_time:
        time_str = measure_time.strftime('%H:%M') if hasattr(measure_time, 'strftime') else str(measure_time)
        return f"{date_str} {time_str}"
    else:
        return date_str

def parse_measurement_sequence(sequence_str):
    """解析测量序号"""
    if not sequence_str:
        return 1
    
    try:
        # 提取数字部分
        numbers = re.findall(r'\d+', str(sequence_str))
        return int(numbers[0]) if numbers else 1
    except:
        return 1

def calculate_age(birth_date):
    """计算年龄"""
    if not birth_date:
        return ""
    
    try:
        from datetime import date
        today = date.today()
        if hasattr(birth_date, 'date'):
            birth_date = birth_date.date()
        
        age = today.year - birth_date.year - ((today.month, today.day) < (birth_date.month, birth_date.day))
        return age if age >= 0 else ""
    except:
        return ""